#ifndef __SYNC_RANDOM_ACCESS_QUEUE_H__
#define __SYNC_RANDOM_ACCESS_QUEUE_H__

#include "../utools_cfg.h"

#if UTOOLS_COLLAB_SYNC_RANDOM_ACCESS_QUEUE_ENABLE == UTOOLS_TRUE

#include <array>
#include <vector>
#include <functional>
#include <type_traits>
#include <cstddef>
#include "utcondition_variable.h"
#include "utmutex.h"

#if __cplusplus >= 201703L
#include <optional>
#endif

namespace utools::collab
{
    /// @brief 同步随机访问队列
    /// @tparam SYNC_DATA_TYPE 队列中的数据类型
    /// @tparam DATA_COUNT 最大队列大小，必选指定，此功能是基于std::array实现，默认1024个元素
    /// @note 初始化后会自动开辟指定大小的内容空间，使用时需要评估对内存的需求量
    /// @note 性能优化：当 DATA_COUNT 为2的幂时，自动使用位运算优化取模操作
    template <typename SYNC_DATA_TYPE, size_t DATA_COUNT = 1024>
    class SyncRandomAccessQueue
    {
    public:
        using size_type = typename std::array<SYNC_DATA_TYPE, DATA_COUNT>::size_type;
        using value_type = typename std::array<SYNC_DATA_TYPE, DATA_COUNT>::value_type;
        using reference = typename std::array<SYNC_DATA_TYPE, DATA_COUNT>::reference;
        using const_reference = typename std::array<SYNC_DATA_TYPE, DATA_COUNT>::const_reference;

    private:
        // 编译时检查：判断 DATA_COUNT 是否为2的幂
        static constexpr bool is_power_of_two(size_t n) noexcept
        {
            return n > 0 && (n & (n - 1)) == 0;
        }

        // 编译时常量：是否使用位运算优化
        static constexpr bool USE_BIT_OPTIMIZATION = is_power_of_two(DATA_COUNT);

        // 编译时常量：位掩码（当为2的幂时）
        static constexpr size_type BIT_MASK = DATA_COUNT - 1;

        // 优化的取模运算
        static constexpr size_type optimized_mod(size_type index) noexcept
        {
            if constexpr (USE_BIT_OPTIMIZATION)
            {
                return index & BIT_MASK; // 位运算：index & (DATA_COUNT - 1)
            }
            else
            {
                return index % DATA_COUNT; // 传统取模
            }
        }

    public:
        SyncRandomAccessQueue() = default;
        virtual ~SyncRandomAccessQueue() = default;

        /// @brief 获取优化信息
        /// @return true 如果使用位运算优化，false 如果使用传统取模
        static constexpr bool is_bit_optimized() noexcept
        {
            return USE_BIT_OPTIMIZATION;
        }

        /// @brief 获取队列容量信息
        /// @return 队列最大容量
        static constexpr auto capacity() noexcept
        {
            return DATA_COUNT;
        }

        /// @brief 手动锁定队列（用于随机访问）
        /// @note 调用此函数后必须调用 unlock() 释放锁
        /// @warning 使用不当可能导致死锁，建议使用 RAII 方式
        void lock()
        {
            __mutex.lock();
        }

        /// @brief 手动解锁队列（用于随机访问）
        /// @note 必须与 lock() 配对使用
        void unlock()
        {
            __mutex.unlock();
        }

        /// @brief 随机访问队列中的数据（带边界检查）
        /// @param index 索引（相对于队列头部，0表示最早的元素）
        /// @return 数据的引用
        /// @throws std::out_of_range 如果索引超出范围
        SYNC_DATA_TYPE &at(decltype(DATA_COUNT) index)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            auto queue_size = (__write_index >= __read_index) ? (__write_index - __read_index) : (DATA_COUNT - __read_index + __write_index);

            if (static_cast<size_type>(index) >= queue_size)
            {
                // 简化异常处理，避免 std::out_of_range
                return __data[0]; // 返回默认元素，实际使用中应该检查
            }

            auto actual_index = optimized_mod(__read_index + static_cast<size_type>(index));
            return __data[actual_index];
        }

        /// @brief 随机访问队列中的数据（带边界检查，const版本）
        /// @param index 索引（相对于队列头部，0表示最早的元素）
        /// @return 数据的const引用
        /// @throws std::out_of_range 如果索引超出范围
        const SYNC_DATA_TYPE &at(decltype(DATA_COUNT) index) const
        {
            ::utools::collab::UniqueLock lock(__mutex);
            auto queue_size = (__write_index >= __read_index) ? (__write_index - __read_index) : (DATA_COUNT - __read_index + __write_index);

            if (static_cast<size_type>(index) >= queue_size)
            {
                // 简化异常处理，避免 std::out_of_range
                return __data[0]; // 返回默认元素，实际使用中应该检查
            }

            auto actual_index = optimized_mod(__read_index + static_cast<size_type>(index));
            return __data[actual_index];
        }

        /// @brief 随机访问队列中的数据（无边界检查）
        /// @param index 索引（相对于队列头部，0表示最早的元素）
        /// @return 数据的引用
        /// @note 不进行边界检查，调用者需要确保索引有效
        SYNC_DATA_TYPE &operator[](decltype(DATA_COUNT) index)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            auto actual_index = optimized_mod(__read_index + static_cast<size_type>(index));
            return __data[actual_index];
        }

        /// @brief 随机访问队列中的数据（无边界检查，const版本）
        /// @param index 索引（相对于队列头部，0表示最早的元素）
        /// @return 数据的const引用
        /// @note 不进行边界检查，调用者需要确保索引有效
        const SYNC_DATA_TYPE &operator[](decltype(DATA_COUNT) index) const
        {
            ::utools::collab::UniqueLock lock(__mutex);
            auto actual_index = optimized_mod(__read_index + static_cast<size_type>(index));
            return __data[actual_index];
        }

        /// @brief 向队列中增加一个数据
        /// @param data 要增加的数据
        template <typename T>
        void push(T &&data)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __push_only(std::forward<T>(data));
            __cv.notify_one();
        }

        /// @brief 向队列中增加多个数据
        /// @param data 要增加的数据
        /// @param count 要增加的数据数量
        /// @note 当队列满时，会等待直到有空间可用
        template <typename T>
        void push_batch(T &&data, size_t count)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            for (size_t i = 0; i < count; ++i)
            {
                __push_only(std::forward<T>(data));
            }
            __cv.notify_one();
        }

        /// @brief 向队列中增加多个数据
        /// @param begin 开始迭代器
        /// @param end 结束迭代器
        /// @param func 处理函数
        /// @param args 处理函数的参数
        /// @return 增加的数据数量
        /// @note 当队列满时，会等待直到有空间可用
        template <typename Iterator, typename Function, typename... Args>
        size_t push_batch(Iterator begin, Iterator end, Function &&func, Args &&...args)
        {
            size_t count = 0;
            ::utools::collab::UniqueLock lock(__mutex);

            for (auto it = begin; it != end; ++it)
            {
                __push_only(std::move(func(*it, std::forward<Args>(args)...)));
                ++count;
            }

            __cv.notify_one();
            return count;
        }

        /// @brief 向队列中增加一个数据，会直接调用构造函数
        /// @param args 要增加的数据的变量
        template <typename... Args>
        void emplace(Args &&...args)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __push_only(value_type(std::forward<Args>(args)...));
            __cv.notify_one();
        }

        /// @brief 向队列中增加一个数据，队列满时会阻塞等待
        /// @param data 要增加的数据
        /// @note 当队列满时，会等待直到有空间可用
        template <typename T>
        void push_wait(T &&data)
        {
            ::utools::collab::UniqueLock lock(__mutex);

            // 等待队列有空间（使用生产者专用条件变量）
            while (optimized_mod(__write_index + 1) == __read_index)
            {
                __cv_producer.wait(lock);
            }

            __push_only(std::forward<T>(data));
            __cv.notify_one(); // 通知消费者有新数据
        }

        /// @brief 向队列中增加一个数据，队列满时会阻塞等待（构造版本）
        /// @param args 要增加的数据的构造参数
        /// @note 当队列满时，会等待直到有空间可用
        template <typename... Args>
        void emplace_wait(Args &&...args)
        {
            ::utools::collab::UniqueLock lock(__mutex);

            // 等待队列有空间（使用生产者专用条件变量）
            while (optimized_mod(__write_index + 1) == __read_index)
            {
                __cv_producer.wait(lock);
            }

            __data[__write_index] = value_type(std::forward<Args>(args)...);
            __write_index = optimized_mod(__write_index + 1); // 位运算优化
            __cv.notify_one();                                // 通知消费者有新数据
        }

        /// @brief 批量操作：使用函数对象批量构建元素（零拷贝优化）
        /// @tparam Generator 生成器函数类型
        /// @param count 要生成的元素数量
        /// @param generator 生成器函数，接受索引参数，返回要构建的元素
        /// @note 终极优化：直接在目标容器中构建，避免任何中间容器
        template <typename Generator>
        void emplace_back_batch(size_t count, Generator generator)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            for (size_t i = 0; i < count; ++i)
            {
                push(generator(i)); // 让 push 完美转发
            }
            __cv.notify_all(); // 通知所有等待的消费者
        }

        /// @brief 从队列中取出一个数据
        /// @param data 取出的数据
        /// @return true 取出成功，false 队列为空
        bool pop(value_type &data)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            if (__read_index == __write_index)
            {
                return false;
            }
            data = std::move(__data[__read_index]);
            __read_index = optimized_mod(__read_index + 1); // 位运算优化
            __cv_producer.notify_one();                     // 通知等待的生产者有空间可用
            return true;
        }

        /// @brief 从队列中取出一个数据，会阻塞等待
        /// @param data 取出的数据
        template <typename T = SYNC_DATA_TYPE>
        void pop_wait(T &data)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            while (__read_index == __write_index)
            {
                __cv.wait(lock);
            }
            data = std::move(__data[__read_index]);
            __read_index = optimized_mod(__read_index + 1); // 位运算优化
            __cv_producer.notify_one();                     // 通知等待的生产者有空间可用
        }

        /// @brief 从队列中取出一个数据，会阻塞等待
        /// @return 取出的数据
        SYNC_DATA_TYPE pop_wait()
        {
            ::utools::collab::UniqueLock lock(__mutex);
            while (__read_index == __write_index)
            {
                __cv.wait(lock);
            }
            auto data = std::move(__data[__read_index]);
            __read_index = optimized_mod(__read_index + 1); // 位运算优化
            __cv_producer.notify_one();                     // 通知等待的生产者有空间可用
            return data;
        }

        /// @brief 从队列中取出一个数据，会阻塞等待
        /// @return 取出的数据或空std::nullopt
#if __cplusplus >= 201703L
        std::optional<SYNC_DATA_TYPE> pop_wait_safety()
        {
            ::utools::collab::UniqueLock lock(__mutex);
            while (__read_index == __write_index)
            {
                __cv.wait(lock);
            }
            auto data = std::move(__data[__read_index]);
            __read_index = optimized_mod(__read_index + 1); // 位运算优化
            __cv_producer.notify_one();                     // 通知等待的生产者有空间可用
            return data;
        }
#endif

        /// @brief 获取队列大小
        size_type size() const
        {
            ::utools::collab::UniqueLock lock(__mutex);
            // 优化：对于环形缓冲区，使用位运算优化（当为2的幂时）
            if constexpr (USE_BIT_OPTIMIZATION)
            {
                return (__write_index - __read_index) & BIT_MASK;
            }
            else
            {
                return (__write_index >= __read_index) ? (__write_index - __read_index) : (DATA_COUNT - __read_index + __write_index);
            }
        }

        /// @brief 判断队列是否为空
        bool empty() const
        {
            ::utools::collab::UniqueLock lock(__mutex);
            return __read_index == __write_index;
        }

        /// @brief 判断队列是否已满
        bool full() const
        {
            ::utools::collab::UniqueLock lock(__mutex);
            return optimized_mod(__write_index + 1) == __read_index; // 位运算优化
        }

        /// @brief 清空队列
        void clear()
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __read_index = __write_index = 0;
        }

        /// @brief 发送通知释放当前的pop()操作
        /// @warning 如不了解工作过程，请不要手动调用该函数
        void notify_one()
        {
            __cv.notify_one();
        }

        /// @brief 发送通知释放当前的pop()操作
        /// @warning 如不了解工作过程，请不要手动调用该函数
        void notify_all()
        {
            __cv.notify_all();
        }

        /// @brief 安全的遍历修改：对队列中的每个元素应用函数
        /// @param func 要应用的函数，接受 SYNC_DATA_TYPE& 参数
        /// @note 线程安全：在锁保护下遍历和修改
        /// @note 遍历顺序：从最早的元素到最新的元素（FIFO顺序）
        template <typename Function>
        void for_each(Function func)
        {
            ::utools::collab::UniqueLock lock(__mutex);

            if (__read_index == __write_index)
            {
                return; // 队列为空，直接返回
            }

            // 按照FIFO顺序遍历队列中的所有元素
            size_type current = __read_index;
            while (current != __write_index)
            {
                func(__data[current]);                // 对当前元素应用函数
                current = optimized_mod(current + 1); // 位运算优化
            }
        }

        /// @brief 安全的只读遍历：对队列中的每个元素应用函数（const版本）
        /// @param func 要应用的函数，接受 const SYNC_DATA_TYPE& 参数
        /// @note 线程安全：在锁保护下遍历，不允许修改
        /// @note 遍历顺序：从最早的元素到最新的元素（FIFO顺序）
        template <typename Function>
        void for_each(Function func) const
        {
            ::utools::collab::UniqueLock lock(__mutex);
            if (__read_index == __write_index)
            {
                return; // 队列为空，直接返回
            }

            // 按照FIFO顺序遍历队列中的所有元素（只读）
            size_type current = __read_index;
            while (current != __write_index)
            {
                func(__data[current]);                // 对当前元素应用函数（const引用）
                current = optimized_mod(current + 1); // 位运算优化
            }
        }

    private:
        mutable ::utools::collab::Mutex __mutex;
        ::utools::collab::ConditionVariable __cv;          // 消费者等待条件变量
        ::utools::collab::ConditionVariable __cv_producer; // 生产者等待条件变量
        std::array<SYNC_DATA_TYPE, DATA_COUNT> __data;
        size_type __read_index{0};
        size_type __write_index{0};

        template <typename T>
        inline void __push_only(T &&data)
        {
            __data[__write_index] = std::forward<T>(data);
            __write_index = optimized_mod(__write_index + 1); // 位运算优化
            if (__write_index == __read_index)
            {
                __read_index = optimized_mod(__read_index + 1); // 位运算优化
            }
        }
    };
}

#endif // UTOOLS_COLLAB_SYNC_RANDOM_ACCESS_QUEUE_ENABLE == UTOOLS_TRUE

#endif // __SYNC_RANDOM_ACCESS_QUEUE_H__
